package com.gitee.wsl.platform.thread.task.bean

import com.gitee.wsl.platform.thread.task.TaskCancellationException
import org.jetbrains.annotations.NonBlocking
import java.util.concurrent.ExecutionException


/**
 * Represents the outcome of a finished task.
 *
 * @param <T> is the type of the value that the task completed with
</T> */
interface Outcome<T> {
    @Throws(ExecutionException::class, TaskCancellationException::class)
    @NonBlocking
    fun getOrThrow(): T

    /**
     * Signals a successful result of the task.
     */
    @JvmRecord
    data class Success<T>(val value: T) : Outcome<T> {

        override fun getOrThrow(): T {
            return value
        }

    }

    /**
     * Signals that the task failed.
     */
    @JvmRecord
    data class Failure<T>(val exception: Throwable?) : Outcome<T> {
        @Throws(ExecutionException::class)
        override fun getOrThrow(): T {
            throw ExecutionException(exception)
        }
    }

    /**
     * Signals that the task was cancelled.
     */
    class Cancellation<T> : Outcome<T> {
        @Throws(TaskCancellationException::class)
        override fun getOrThrow(): T {
            throw TaskCancellationException()
        }

        companion object {
            val INSTANCE: Cancellation<Nothing> = Cancellation()
        }
    }

    companion object {
        fun <T> success(value: T): Outcome<T> {
            return Success(value)
        }

        fun <T> failure(error: Throwable?): Outcome<T> {
            return Failure(error)
        }

        fun <T> cancellation(): Outcome<T> {
            return Cancellation.INSTANCE as Outcome<T>
        }
    }
}
